{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to the Planner\n",
    "\n",
    "The Planner is one of the fundamental concepts of the Semantic Kernel. It makes use of the collection of plugins that have been registered to the kernel and using AI, will formulate a plan to execute a given ask.\n",
    "\n",
    "Read more about it [here](https://aka.ms/sk/concepts/planner)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "#r \"nuget: Microsoft.SemanticKernel, 1.0.0-beta6\"\n",
    "\n",
    "#!import config/Settings.cs\n",
    "#!import config/Utils.cs\n",
    "\n",
    "using Microsoft.SemanticKernel;\n",
    "using Microsoft.SemanticKernel.Plugins.Core;\n",
    "using Microsoft.SemanticKernel.Orchestration;\n",
    "using Microsoft.SemanticKernel.Planning;\n",
    "using Microsoft.SemanticKernel.Planners;\n",
    "using Microsoft.SemanticKernel.Connectors.AI.OpenAI;\n",
    "\n",
    "var builder = new KernelBuilder();\n",
    "\n",
    "// Configure AI backend used by the kernel\n",
    "var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
    "\n",
    "if (useAzureOpenAI)\n",
    "    builder.WithAzureOpenAIChatCompletionService(model, azureEndpoint, apiKey);\n",
    "else\n",
    "    builder.WithOpenAIChatCompletionService(model, apiKey, orgId);\n",
    "\n",
    "var kernel = builder.Build();"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setting Up the Planner\n",
    "The planner is located in the `Microsoft.SemanticKernel.Planners.Core` package and requires Orchestration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Load native plugin into the kernel registry, sharing its functions with prompt templates\n",
    "var planner = new SequentialPlanner(kernel);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Providing plugins to the planner\n",
    "The planner needs to know what plugins are available to it. Here we'll give it access to the `SummarizePlugin` and `WriterPlugin` we have defined on disk."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"..\", \"..\", \"samples\", \"plugins\");\n",
    "kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"SummarizePlugin\");\n",
    "kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"WriterPlugin\");"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define your ASK. What do you want the Kernel to do?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "var ask = \"Tomorrow is Valentine's day. I need to come up with a few date ideas. My significant other likes poems so write them in the form of a poem.\";\n",
    "var originalPlan = await planner.CreatePlanAsync(ask);\n",
    "\n",
    "Console.WriteLine(\"Original plan:\\n\");\n",
    "Console.WriteLine(JsonSerializer.Serialize(originalPlan, new JsonSerializerOptions { WriteIndented = true }));"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see in the above plan, the Planner has taken the user's ask and converted it into a Plan object detailing how the AI would go about solving this task.\n",
    "\n",
    "It makes use of the plugins that the Kernel has available to it and determines which functions to call in order to fulfill the user's ask.\n",
    "\n",
    "The output of each step of the plan gets set as `setContextVariable` which makes it available as `input` to the next plugin."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's also define an inline plugin and have it be available to the Planner.\n",
    "Be sure to give it a function name and plugin name."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "string skPrompt = \"\"\"\n",
    "{{$input}}\n",
    "\n",
    "Rewrite the above in the style of Shakespeare.\n",
    "\"\"\";\n",
    "var shakespeareFunction = kernel.CreateSemanticFunction(skPrompt, \"Shakespeare\", \"ShakespearePlugin\", requestSettings: new OpenAIRequestSettings { MaxTokens = 2000, Temperature = 0.2, TopP = 0.5 });"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's update our ask using this new plugin."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "var ask = @\"Tomorrow is Valentine's day. I need to come up with a few date ideas.\n",
    "She likes Shakespeare so write using his style. Write them in the form of a poem.\";\n",
    "\n",
    "var newPlan = await planner.CreatePlanAsync(ask);\n",
    "\n",
    "Console.WriteLine(\"Updated plan:\\n\");\n",
    "Console.WriteLine(JsonSerializer.Serialize(newPlan, new JsonSerializerOptions { WriteIndented = true }));"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Executing the plans\n",
    "\n",
    "Now that we have different plans, let's try to execute them! The Kernel can execute the plan using RunAsync."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "var originalPlanResult = await kernel.RunAsync(originalPlan);\n",
    "\n",
    "Console.WriteLine(\"Original Plan results:\\n\");\n",
    "Console.WriteLine(Utils.WordWrap(originalPlanResult.GetValue<string>(), 100));"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets execute and print the new plan:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "var newPlanResult = await kernel.RunAsync(newPlan);\n",
    "\n",
    "Console.WriteLine(\"New Plan results:\\n\");\n",
    "Console.WriteLine(newPlanResult.GetValue<string>());"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
